package net.interneteidee.utility;

import java.util.LinkedList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

import net.interneteidee.entity.Categoria;
import net.interneteidee.entity.Cliente;
import net.interneteidee.entity.Famiglia;
import net.interneteidee.entity.Fattura;
import net.interneteidee.entity.LineaFattura;
import net.interneteidee.entity.LineaOrdine;
import net.interneteidee.entity.Ordine;
import net.interneteidee.entity.Prodotto;
import net.interneteidee.servizi.ClienteService;
import net.interneteidee.servizi.OrdineFatturaService;
import net.interneteidee.servizi.ProdottoCategoriaFamigliaService;

@ManagedBean
@SessionScoped
public class TabsBean implements ComponentName {

	private List<GenericTab> tabs;
	
	private String activeTab;
	private String prevActiveTab;
	private String nextTab;
	private long codiceProdotto;
		
	@Inject
	ClienteService clienteService;

	@Inject
	ProdottoCategoriaFamigliaService prodottoCategoriaFamigliaService;

	@Inject
	OrdineFatturaService ordineFatturaService;

	@SuppressWarnings("rawtypes")
	TabRisultati tabRisultati = null;
	
	TabRicerche tabRicerche = null;

	private LineaOrdine lineaOrdine = null;
	private LineaFattura lineaFattura = null;
	private int indiceLineaOrdineSelezionata;
	
	private String tabDaEliminare;

	public TabsBean() {
		tabs = new LinkedList<GenericTab>();
		activeTab = "Dash";
		
	}

	public void tabChange() {

		//Questo viene invocato perchè l'eliminazione di una tab invoca anche questa funzione 
		//quindi mi devo assicurare che i dati vengano aggiornati solo dall' evento
		//headerClick
		if(esisteTab(nextTab)){
			prevActiveTab = activeTab;
			activeTab = nextTab;
		}
	
	}

	public void creaTabRisultatiNew(String tabName, String path) {

		if (!esisteTab(tabName)) {
			if (tabName.equals(tabFamiglie) || tabName.equals(tabResocontoCliente)) {
				tabRisultati = new TabRisultati<Famiglia>();
				tabRisultati.setObject(new Famiglia());
			} else if (tabName.equals(tabCategorie)) {
				tabRisultati = new TabRisultati<Categoria>();
				tabRisultati.setObject(new Categoria());

			} else if (tabName.equals(tabProdotti)) {
				tabRisultati = new TabRisultati<Prodotto>();
				tabRisultati.setObject(new Prodotto());

			} else if (tabName.equals(tabClienti)) {
				tabRisultati = new TabRisultati<Cliente>();
				tabRisultati.setObject(new Cliente());

			} else if (tabName.equals(tabOrdini)) {
				tabRisultati = new TabRisultati<Ordine>();
				tabRisultati.setObject(new Ordine());
				
			}else if (tabName.equals(tabFatture)) {
				tabRisultati = new TabRisultati<Fattura>();
				tabRisultati.setObject(new Fattura());
			}else if(tabName.equals(tabRiepilogoVenduto)) {
				tabRicerche = new TabRicerche();
			}

			tabRisultati.setName(tabName);
			tabRisultati.setPathDaIncludere(path);

			tabs.add(tabRisultati);

		}
		
		if(!isTabAttiva(tabName))
			updatNomeTabAperta(tabName);
		

	}
	
	
	public void creaTabModificaOrdine(String tabName, String path , Ordine ordine){
		
		if(!esisteTab(tabName)){
			
			tabRisultati = new TabRisultati<Ordine>();
			tabRisultati.setObject(ordine);
			
			tabRisultati.setName(tabName);
			tabRisultati.setPathDaIncludere(path);
			tabs.add(tabRisultati);
			updatNomeTabAperta(tabName);
			
		}
		
		if(!isTabAttiva(tabName))
			updatNomeTabAperta(tabName);
		
	}
	
	public void creaTabModificaFattura(String tabName, String path , Fattura fattura){
		
		if(!esisteTab(tabName)){
			
			tabRisultati = new TabRisultati<Fattura>();
			tabRisultati.setObject(fattura);
			
			tabRisultati.setName(tabName);
			tabRisultati.setPathDaIncludere(path);
			tabs.add(tabRisultati);
			updatNomeTabAperta(tabName);
			
		}
		
		if(!isTabAttiva(tabName))
			updatNomeTabAperta(tabName);
		
	}
	
	public void creaTabRiepilogo(String tabName, String path){
		
		if(!esisteTab(tabName) ){
			
			tabRicerche = new TabRicerche();
			tabRicerche.setName(tabName);
			tabRicerche.setPathDaIncludere(path);
			tabs.add(tabRicerche);
			updatNomeTabAperta(tabName);
		
		}
		if(!isTabAttiva(tabName))
			updatNomeTabAperta(tabName);
		
		
	}

	public void removeTab() {
		
		tabs.remove(getTabByName(tabDaEliminare));
		activeTab = prevActiveTab;
	}
	
	/**
	 * Controlla se la tab con tabName è la tab Attiva 
	 * @param tabName
	 * @return
	 */
	private boolean isTabAttiva(String tabName){
		
		return tabName == activeTab;
		
	}
	
	/**
	 * Questa funzione viene invocata quando c'e stato un evento
	 * che ha avuto come effetto lo swith tra le table
	 * @param nameTab
	 */
	private void updatNomeTabAperta(String nameTab){
		prevActiveTab = activeTab;
		activeTab = nameTab;
	}

	private boolean esisteTab(String nome) {

		for (GenericTab tab : tabs)
			if (nome.equals(tab.getName()))
				return true;
		return false;
	}

	private GenericTab getTabByName(String name) {

		for (GenericTab tab : tabs)
			if (tab.getName().equals(name))
				return  tab;

		return null;

	}
	
	
	

	/**
	 * Porto in memoria tutte le famiglie
	 */
	public void findAllFAmiglie() {

		TabRisultati<Famiglia> tab =  (TabRisultati<Famiglia>) getTabByName(tabFamiglie);
		tab.setRisultati(prodottoCategoriaFamigliaService.findAllFamiglie());
		System.out.println("Numero Famiglie "+prodottoCategoriaFamigliaService.findAllFamiglie().size());
	}

	public void findAllCategorie() {

		TabRisultati<Categoria> tab = (TabRisultati<Categoria>) getTabByName(tabCategorie);
		tab.setRisultati(prodottoCategoriaFamigliaService.findAllCategorie());

	}

	public void findAllClienti() {

		TabRisultati<Cliente> tab = (TabRisultati<Cliente>) getTabByName(tabClienti);
		tab.setRisultati(clienteService.findAllClients());

	}


	
	
	public void findAllFatture() {
		TabRisultati<Fattura> tab = (TabRisultati<Fattura>) getTabByName(tabFatture);
		tab.setRisultati(ordineFatturaService.findAllFatture());
	}

	// ---------Gestione Ordine----------------------------------------------------------------------
	
	
	public void creaNuovoOrdine(String tabName){
		TabRisultati<Ordine> tab = (TabRisultati<Ordine>) getTabByName(tabName);
		tab.setObject(new Ordine());
		tab.setStatusRecord("Creazione Ordine");
		
	}
	
	
	public void addLineaOrdine(String tabName) {
		lineaOrdine = new LineaOrdine();
		TabRisultati<Ordine> tab = (TabRisultati<Ordine>) getTabByName(tabName);
		tab.getObject().addLineaOrdine(lineaOrdine);
	}

	public void deleteLineaOrdine(String tabName) {
		TabRisultati<Ordine> tab = (TabRisultati<Ordine>) getTabByName(tabName);
		tab.getObject().getLineeOrdine().remove(indiceLineaOrdineSelezionata);

	}

	public void addProdottoALineaOrdine(Prodotto prodotto , String tabName) {
		TabRisultati<Ordine> tab = (TabRisultati<Ordine>) getTabByName(tabName);
		tab.getObject().getLineeOrdine().get(indiceLineaOrdineSelezionata)
				.setProdotto(prodotto);
	}
	
	public void addOrdine(Ordine ordine,String tabName) {
		try{
			ordineFatturaService.addOrdine(ordine);
			setStatusRecord("Ordine "+ordine.getCodiceOrdine()+" memorizzato con successo", tabName);
		}
		catch (Exception e) {
			setStatusRecord("Errore nel salvataggio dell ordine", tabName);
		}
		
	}
	
	public void findAllOrdini() {

		TabRisultati<Ordine> tab = (TabRisultati<Ordine>) getTabByName(tabOrdini);
		tab.setRisultati(ordineFatturaService.findAllOrdini());

	}
	
	// ----------------Fine Gestione Ordine ------------------------
	
	
	//--------------Gestione Fattura-------------------------------
	public void addLineaFattura(String tabName) {
		lineaFattura = new LineaFattura();
		TabRisultati<Fattura> tab = (TabRisultati<Fattura>) getTabByName(tabName);
		tab.getObject().addLineaFattura(lineaFattura);
	}
	
	public void deleteLineaFattura(String tabName) {
		TabRisultati<Fattura> tab = (TabRisultati<Fattura>) getTabByName(tabName);
		tab.getObject().getLineeFattura().remove(indiceLineaOrdineSelezionata);

	}
	
	public void addProdottoALineaFattura(Prodotto prodotto,String tabName) {
		TabRisultati<Fattura> tab = (TabRisultati<Fattura>) getTabByName(tabName);
		tab.getObject().getLineeFattura().get(indiceLineaOrdineSelezionata)
				.setProdotto(prodotto);
	}
	
	public void addFattura(Fattura fattura,String tabName){
		
		try{
			ordineFatturaService.addFattura(fattura);
			setStatusRecord("Fattura "+fattura.getCodiceFattura()+" salvata con successo", tabName);
		}
		catch (Exception e) {
			// TODO: handle exception
			setStatusRecord("Errore nel salvataggio della Fattura "+fattura.getCodiceFattura(), tabName);
		}
		
	}
	
	//----------------------------------------------------------------------------
	
	
	
	//-----------------------Gestione Famiglia------------------------------------
	public void addFamiglia(Famiglia famiglia) {
		try{
			prodottoCategoriaFamigliaService.addFamiglia(famiglia);
			setStatusRecord("Famiglia "+famiglia.getNome()+" salvata con successo", tabFamiglie);
		}
		catch (Exception e) {
			// TODO: handle exception
			setStatusRecord("Errore nel salvataggio della famiglia", tabFamiglie);
		}
	}

	public void creaNuovaFamiglia(String tabName){
		TabRisultati<Famiglia> tab = (TabRisultati<Famiglia>) getTabByName(tabName);
		tab.setObject(new Famiglia());
		tab.setStatusRecord("Creazione Famiglia");
		
	}
	
	//-----------------------------------------------------------------------------------
	
	//-----------------------Gestione Categoria------------------------------------------
	public void addCategoria(Categoria categoria) {
		try{
			prodottoCategoriaFamigliaService.addCategoria(categoria);
			setStatusRecord("Categoria "+categoria.getNome()+" salvata con successo", tabCategorie);
		}
		catch (Exception e) {
			// TODO: handle exception
			setStatusRecord("Errore nel salvataggio della categoria ", tabCategorie);

		}
	}

	public void creaNuovaCategoria(String tabName){
		TabRisultati<Categoria> tab = (TabRisultati<Categoria>) getTabByName(tabName);
		tab.setObject(new Categoria());
		tab.setStatusRecord("Creazione Famiglia");
	}
	
	//------------------------------------------------------------------------------------
	
	
	
	//--------------------------Gestione Prodotto-----------------------------------------
	
	public void addProdotto(Prodotto prodotto) {
		try{
			prodottoCategoriaFamigliaService.addProdotto(prodotto);
			setStatusRecord("Categoria "+prodotto.getCodiceProdotto()+" salvato con successo", tabProdotti);
		}
		catch (Exception e) {
			setStatusRecord("Errore nel salvataggio del Prodotto "+prodotto.getCodiceProdotto(), tabProdotti);
		}
	}
	
	/**
	 * Controlla se i codici di prodotto Fattura e Ordine sono già presenti sul DB 
	 * @param codice
	 * @param tabName
	 */
	public void checkIfCodiceExist(long codice , String tabName,String componentId){

		if(tabName.contains("Prodotti")){
			if(prodottoCategoriaFamigliaService.findProdottoByCodice(codice))
				creaMessaggioErroreCodiceGiaPresente(tabName,componentId,codice);
		}
		else if(tabName.contains("Ordine")){
			if(ordineFatturaService.findOrdineByCodice(codice))
				creaMessaggioErroreCodiceGiaPresente(tabName,componentId,codice);
		}
		else if(tabName.contains("Fattura")){
			if(ordineFatturaService.findFatturaByCodice(codice))
				creaMessaggioErroreCodiceGiaPresente(tabName,componentId,codice);
		}
			
		
	}
	
	
	
	public void findAllProdotti() {

		TabRisultati<Prodotto> tab = (TabRisultati<Prodotto>) getTabByName(tabProdotti);
		tab.setRisultati(prodottoCategoriaFamigliaService.findAllProdotti());

	}
	
	//----------------Fine Gestione Prodotto--------------------------------------------
	
	

	public void addCliente(Cliente cliente) {
		clienteService.addClient(cliente);
	}

	
	
	
	private void setStatusRecord(String statusRecord , String tabName){
		getTabByName(tabName).setStatusRecord(statusRecord);
	}
	
	private void creaMessaggioErroreCodiceGiaPresente(String tabName,String componentId,long codice){
		FacesContext faceContext = FacesContext.getCurrentInstance(); //Instead of doing like this create some boolean variable with false and set as true inside this method
		FacesMessage facesMessage = new FacesMessage("Codice "+codice+" presente nel DB ");//if email already exist in the DB means and just render the <h:output text in the screen with color red.
		facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR); // it shows like error in the screen.       
		faceContext.addMessage("form"+tabName+":"+componentId, facesMessage);
	}
	
	

	public List<GenericTab> getTabs() {
		return tabs;
	}

	public void setTabs(List<GenericTab> tabs) {
		this.tabs = tabs;
	}

	public String getActiveTab() {
		return activeTab;
	}

	public void setActiveTab(String activeTab) {
		this.activeTab = activeTab;
	}

	public LineaOrdine getLineaOrdine() {
		return lineaOrdine;
	}

	public void setLineaOrdine(LineaOrdine lineaOrdine) {
		this.lineaOrdine = lineaOrdine;
	}

	public int getIndiceLineaOrdineSelezionata() {
		return indiceLineaOrdineSelezionata;
	}

	public void setIndiceLineaOrdineSelezionata(int indiceLineaOrdineSelezionata) {
		this.indiceLineaOrdineSelezionata = indiceLineaOrdineSelezionata;
	}

	public String getTabDaEliminare() {
		return tabDaEliminare;
	}

	public void setTabDaEliminare(String tabDaEliminare) {
		this.tabDaEliminare = tabDaEliminare;
	}

	public String getPrevActiveTab() {
		return prevActiveTab;
	}

	public void setPrevActiveTab(String prevActiveTab) {
		this.prevActiveTab = prevActiveTab;
	}

	public String getNextTab() {
		return nextTab;
	}

	public void setNextTab(String nextTab) {
		this.nextTab = nextTab;
	}

	public long getCodiceProdotto() {
		return codiceProdotto;
	}

	public void setCodiceProdotto(long codiceProdotto) {
		this.codiceProdotto = codiceProdotto;
	}
	
	
	

}
